<?php

namespace IDock\Insurance\DAJIA;

use IDock\Common\BaseInterface\BuilderInterface;
use IDock\Http\Request;
use IDock\Http\Response;
use IDock\Insurance\DAJIA\Request\AllDAJIARequest;
use IDock\Insurance\DAJIA\Response\AllDAJIAResponse;

class Builder implements BuilderInterface
{
    protected $ip;

    protected $config;

    protected $channelCode;

    protected $channelPwd;

    protected $interCode;

    protected $secretKey;

    protected $deviceType;

    protected $transTime;

    public function getConfig(): array
    {
        return  $this->config;
    }

    public function execute(Request $request): Response
    {
        /*** @var AllDAJIARequest $request */
        $request->loadConfig($this->config);
        $this->transTime = date('Y-m-d H:i:s');

        $reqSerialNo = $this->channelCode . '_' . date('Ymd') . '_' . rand(10000000, 99999999);

        $request->setRequestId($reqSerialNo);

        $param = [
            'reqSerialNo' => $reqSerialNo,
            'channelCode' => $this->channelCode,
            'channelPwd' => $this->channelPwd,
            'deviceType' => $this->deviceType,
            'interCode' => $request->getCode(),
            'transTime' => $this->transTime,
            'body' => $this->generate($request)
        ];
        $request->setPreParameter($param);

        $this->sign($request);
        return $this->request($request);
    }

    public function generate(Request $request): array
    {
        return $request->generate();
    }

    public function sign(Request $request): Request
    {
        $bizParam = [
            'timestamp' => $this->getMicroTime(),
        ];
        $bizParam['data'] = $this->encrypt($request);
        $salt1 = substr($bizParam['timestamp'], 0, 4);
        $salt2 = substr($bizParam['timestamp'], 4, 4);
        $salt3 = substr($bizParam['timestamp'], -5);

        $md5 = md5($salt1 . $bizParam['data'] . $salt2 . $this->secretKey . $salt3);

        $bizParam['signature'] = $md5;

        $request->setBizParam($bizParam);

        return $request;
    }

    private function getMicroTime()
    {
        list($microsecond, $second) = explode(' ', microtime());
        return intval(($microsecond + $second) * 1000);
    }

    public function exceptionResponse($request, $errorMessage): Response
    {
        $response = $request->getResponse();

        $response = new $response;
        $response->setCode('500');
        $response->setError($errorMessage);

        return $response;
    }

    public function request(Request $request): Response
    {
        /**
         * @var AllDAJIAResponse $response
         */
        $response = $request->request($request);
        $response->decrypt($this->secretKey, $request);
        $response->setVisitor($request->getVisitor());
        if($response->isSuccess()) {
            $response->printerInit();
        }
        return $response;
    }

    /**
     * 数据加密
     * @param Request $request
     * @return string
     */
    public function encrypt(Request $request)
    {
        $data = json_encode($request->getPreParameter());
        //对应java AES加密的SHA1PRNG算法
        $realKey = substr(openssl_digest(openssl_digest($this->secretKey, 'sha1', true), 'sha1', true), 0, 16);
        $ciphertext = openssl_encrypt($data, 'aes-128-ecb', $realKey, OPENSSL_RAW_DATA);
        return strtoupper(bin2hex($ciphertext));
    }
}
